package cn.net.autocode.platform.table;

import cn.hutool.core.util.StrUtil;
import cn.net.autocode.core.bean.ResultT;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.dbManager.IdWorker;
import cn.net.autocode.dbManager.SqlWrapper;
import cn.net.autocode.dbManager.SqlWrapperBuilder;
import cn.net.autocode.platform.config.SpringProfileConfig;
import cn.net.autocode.platform.design.handle.AutoCodeHandle;
import cn.net.autocode.platform.design.vo.AppInfo;
import cn.net.autocode.platform.design.vo.DeveloperInfo;
import cn.net.autocode.platform.table.ddl.DataBaseDDL;
import cn.net.autocode.platform.table.ddl.DatabaseDDLFactory;
import cn.net.autocode.platform.table.process.DataModelProcess;
import cn.net.autocode.platform.table.service.TableServ;
import cn.net.autocode.platform.table.syncs.SyncFromDb;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@Slf4j
@RestController("platformTableTree")
@RequestMapping("platform/tableTree")
public class TableTree {

    private final Dao dao;

    private final Dao dictDao;

    private final TableServ serv;

    private final SpringProfileConfig profileConfig;

    public TableTree(Dao dao, @Qualifier("dictDao") Dao dictDao, TableServ serv, SpringProfileConfig profileConfig) {
        this.dao = dao;
        this.dictDao = dictDao;
        this.serv = serv;
        this.profileConfig = profileConfig;
    }

    @RequestMapping("load")
    public ResultT load(@RequestBody JSONObject param){
        JSONArray array;
        //查询表信息
        SqlWrapperBuilder swb = new SqlWrapperBuilder("ac_table");
        if(StrUtil.isNotBlank(param.getString("keyWord"))){
            String keyWord = "%"+param.getString("keyWord").trim()+"%";
            swb.where("(table_name like ? or code like ? or remarks like ?)",keyWord,keyWord,keyWord);
        }
        swb.orderBy("code");
        SqlWrapper sqlWrapper = swb.sqlWrapper();
        JSONArray tables = dictDao.queryJSONArray(sqlWrapper.getSql(),sqlWrapper.getParams().toArray());

        //查询分组信息
        array = dictDao.queryJSONArray("select t1.code id,t1.code,t1.label,'category' type from ac_table_category t1 order by t1.code");

        int size = tables.size();
        for(int i=0;i<size;i++){
            JSONObject table = tables.getJSONObject(i);
            table.put("isLeaf",true);
            table.put("type","table");
            table.put("label",table.getString("tableName"));
            String cateGoryCode = table.getString("categoryCode");
            if("Default".equals(cateGoryCode)||StrUtil.isBlank(cateGoryCode)){
                cateGoryCode = "default";
                dictDao.executeUpdate("update ac_table set is_sync='N',category_code='default' where id=?",table.getString("id"));
            }

            for(int j=0;j<array.size();j++){
                JSONObject parentJson = array.getJSONObject(j);
                if(parentJson.getString("code").equals(cateGoryCode)){
                    if(parentJson.containsKey("children")){
                        parentJson.getJSONArray("children").add(table);
                    }else{
                        JSONArray children = new JSONArray();
                        children.add(table);
                        parentJson.put("children",children);
                    }
                    break;
                }

            }
        }
        return ResultT.success(array);
    }


    @RequestMapping("addCategory")
    public ResultT addCategory(@RequestBody JSONObject param){
        int num = dictDao.queryValue("select count(*) from ac_table_category where code=?", Integer.class, param.getString("code"));
        param.put("id",param.getString("code"));
        param.put("type","category");
        if(num==0){
            dictDao.createJSON(param,"ac_table_category");
        }else{
            dictDao.executeUpdate("update ac_table_category set label=? where code=?", param.getString("label"),param.getString("code"));
        }
        return ResultT.success(param);
    }


    @RequestMapping("delCategory")
    public ResultT delCategory(@RequestBody JSONObject param){
        int tableName = dictDao.queryValue("select count(*) from ac_table where category_code=?", Integer.class, param.getString("code"));
        if(tableName>0){
            return ResultT.fail("该目录下有数据库表信息，禁止删除！");
        }

        if("default".equals(param.getString("code"))){
            return ResultT.fail("default目录不允许进行删除！");
        }
        dictDao.executeUpdate("delete from ac_table_category where code=?",param.getString("code"));
        return ResultT.success();

    }

    @RequestMapping("syncFromDb")
    public ResultT SyncFromDb(@RequestBody JSONObject param){

        DataModelProcess dataModelProcess = new DataModelProcess(this.dao);

        JSONArray tables;
        String id =  param.getString("id");
        if(StrUtil.isNotBlank(id)){
            String tableName = dictDao.queryValue("select table_name from ac_table where id=?",String.class,id);
            tables = dataModelProcess.process(tableName);
        }else{
            tables = dataModelProcess.process();
        }

        //数据同步
        SyncFromDb sync = new SyncFromDb(dictDao);
        sync.execute(tables);
        return ResultT.success();
    }

    @RequestMapping("addTable")
    public ResultT addTable(@RequestBody JSONObject param){
        param.put("id", IdWorker.ulid());
        param.put("tableName",param.getString("tableName").toLowerCase().trim());
        param.put("type","table");
        if(StrUtil.isBlank(param.getString("code"))){
            param.put("code",StrUtil.toCamelCase(param.getString("tableName")));
        }
        //判断表是否存在
        int isExists = dictDao.queryValue("select count(*) from ac_table where table_name=?",Integer.class,param.getString("tableName"));
        if(isExists>0){
            return ResultT.fail(param.getString("tableName")+"已经存在");
        }

        //创建表
        DataBaseDDL ddl;
        try {
            ddl= DatabaseDDLFactory.newInstance(dao);
            ddl.createTable(param.getString("tableName"));
        } catch (Exception e) {
            return ResultT.fail(e.getMessage());
        }

        //添加信息
        param.put("isSync","N");
        dictDao.createJSON(param,"ac_table");

        //添加列信息
        JSONObject fieldJson = new JSONObject();
        fieldJson.put("id", IdWorker.ulid());
        fieldJson.put("tableId",param.getString("id"));
        fieldJson.put("name","id");
        fieldJson.put("type","VARCHAR");
        fieldJson.put("length",36);
        fieldJson.put("scale",0);
        fieldJson.put("isnullable","N");
        fieldJson.put("primaryKey","Y");
        fieldJson.put("remarks","主键");
        fieldJson.put("sortNo",0);
        dictDao.createJSON(fieldJson,"ac_table_fields");

        fieldJson.put("id", IdWorker.ulid());
        fieldJson.put("tableId",param.getString("id"));
        fieldJson.put("name","sort_no");
        fieldJson.put("type","INT");
        fieldJson.put("length",12);
        fieldJson.put("scale",0);
        fieldJson.put("isnullable","Y");
        fieldJson.put("primaryKey","N");
        fieldJson.put("sortNo",1);
        fieldJson.put("remarks","序号");
        dictDao.createJSON(fieldJson,"ac_table_fields");

        fieldJson.put("id", IdWorker.ulid());
        fieldJson.put("tableId",param.getString("id"));
        fieldJson.put("name","remark");
        fieldJson.put("type","VARCHAR");
        fieldJson.put("length",255);
        fieldJson.put("scale",0);
        fieldJson.put("isnullable","Y");
        fieldJson.put("primaryKey","N");
        fieldJson.put("sortNo",2);
        fieldJson.put("remarks","备注");
        dictDao.createJSON(fieldJson,"ac_table_fields");
        return ResultT.success(param);
    }

    @RequestMapping("delTable")
    public ResultT delTable(@RequestBody JSONObject param){
        String id = param.getString("id");
        if(StrUtil.isBlank(id)){
            return ResultT.fail("参数有误");
        }
        JSONObject tableJson = dictDao.queryJSON("select * from ac_table where id=?",id);
        if(tableJson.isEmpty()){
            return ResultT.fail("参数有误");
        }
        String dropTable = "drop table "+tableJson.getString("tableName");
        try {
            if(dao.checkTable(tableJson.getString("tableName"))){
                dao.executeUpdate(dropTable);
            }
        } catch (Exception e) {
            return ResultT.fail(e.getMessage());
        }
        //删除表设计
        dictDao.executeUpdate("delete from ac_table_fields where table_id=?",id);
        dictDao.executeUpdate("delete from ac_table_ref where table_id=?",id);
        dictDao.executeUpdate("delete from ac_table_rules where table_id=?",id);
        dictDao.executeUpdate("delete from ac_table where id=?",id);

        //记录删除日志
        if("dev".equals(profileConfig.getProfile())){
            AppInfo appInfo = AutoCodeHandle.getAppInfo();
            DeveloperInfo developerInfo = AutoCodeHandle.getDeveloperInfo();
            if(appInfo!=null && developerInfo!=null){
                dictDao.executeUpdate("insert into ac_table_del(table_name,del_time,license,del_user) values(?,?,?,?)",tableJson.getString("tableName"),new Date(),appInfo.getLicense(), developerInfo.getUsername());
            }

        }
        //删除关联关系
        dictDao.executeUpdate("update ac_table set is_sync='N' where exists(select 1 from ac_table_ref where ac_table.id=ac_table_ref.table_id and ac_table_ref.fk_table=?)",tableJson.getString("tableName"));
        dictDao.executeUpdate("delete from ac_table_ref where fk_table =?",tableJson.getString("tableName"));

        return ResultT.success();

    }

    @PostMapping(value = "/syncFromServer", produces = "application/json;charset=UTF-8")
    public ResultT syncFromServer(@RequestBody JSONObject param) {
        serv.syncFromServer(param);
        return ResultT.success();
    }

    @RequestMapping("/nodeDrop")
    public ResultT nodeDrop(@RequestBody JSONObject param) {
        dictDao.executeUpdate("update ac_table set category_code=?,is_sync='N' where id=?",param.getString("categoryCode"),param.getString("id"));
        return ResultT.success();
    }
}
